//
//  EasepodsDB.swift
//  GlassDatabase
//
//  Created by 李然 on 2023/5/19.
//

import Foundation
import RealmSwift
import RxRealm
import RxSwift
import SwiftDate
import MoyoungLib

public enum EasepodsDB {
    
    static let realm = try! Realm()
    
    /// 保存和更新对象
    /// - Parameter object: 继承Storable的对象
    public static func save<T: Storable>(object: T) {
        
        do {
            try realm.write {
                realm.add(object, update: .all)
            }
        } catch {
            log.debug(error.localizedDescription)
        }
    }
    
    /// 删除对象
    /// - Parameter object: 继承Storable的对象
    public static func delete<T: Storable>(object: T) {
        do {
            try realm.write {
                realm.delete(object)
            }
        } catch {
            log.debug(error.localizedDescription)
        }
    }
    
    /// 删除所有
    /// - Parameter objects: 继承Storable的数组对象
    public static func deleteAll<T: Storable>(type: T.Type) {
        do {
            try realm.write {
                realm.delete(realm.objects(type))
            }
        } catch {
            log.debug(error.localizedDescription)
        }
    }
    
    
    /// 更新数据
    /// - Parameter block: 在 block里修改对象的信息
    public static func update(_ block: (() -> Void)) {
        do {
            try realm.write {
                block()
            }
        } catch {
            log.debug(error.localizedDescription)
        }
    }
    
    /// 查询所有
    /// - Parameter type: 查询对象类型
    /// - Returns: 对象数组
    public static func getAll<T: Storable>(type: T.Type) -> [T] {
        return realm.objects(type).toArray()
    }
    
    /// 查询所有，可实时监听数据变更
    /// - Parameter type: 查询对象类型
    public static func rxGetAll<T: Storable>(type: T.Type) -> Observable<[T]> {
        let objects = realm.objects(type)
        return Observable.array(from: objects)
    }
    
    /// 查询第一个数据
    public static func queryFirst<T: Storable>(type: T.Type) -> T? {
        
        let objects = realm.objects(type)
        return objects.sorted(by: { $0.date < $1.date }).first
    }
    
    /// 查询一段时间的数据
    /// - Parameters:
    ///   - type: 模型
    ///   - start: 开始时间
    ///   - end: 结束时间
    /// - Returns: 数组
    public static func query<T: Storable>(type: T.Type,
                                           start: Date,
                                           end: Date) -> [T] {
        let objects = realm.objects(type).where { model in
            let isDateInRnage = model.date <= end && model.date >= start
            //if let macAddress = macAddress {
            //    return (model.address == macAddress) && isSameDay
            //}
            return isDateInRnage
        }
        
        var models = objects.toArray()
        var modelsDict = [String: T]()
        models.forEach { s in
            modelsDict[s.date.toFormat("yyyyMMdd")] = s
        }
        
        var dataList: [T] = []
        let days = start.difference(in: .day, from: end) ?? 0
        for i in 0...days {
            let curDate = start + i.days
            let curDateStr = curDate.toFormat("yyyyMMdd")
            if let dayData = modelsDict[curDateStr] {
                dataList.append(dayData)
            } else {
                let t = T.init()
                t.date = curDate
                dataList.append(t)
            }
        }
        return dataList
    }
    
    /// 查询某天的数据
    public static func queryDay<T: Storable>(type: T.Type,
                                             from date: Date) -> T? {
        let calendar = Calendar.current
        let components = calendar.dateComponents([.year, .month, .day], from: date)
        let truncatedDate = calendar.date(from: components)!
        
        let predicate = NSPredicate(format: "date >= %@ AND date < %@", argumentArray: [truncatedDate, calendar.date(byAdding: .day, value: 1, to: truncatedDate)!])
        let objects = realm.objects(type).filter(predicate)
        return objects.first
    }
    
    /// 查询过去七天的数据
    public static func queryLastSevenDay<T: Storable>(type: T.Type,
                                                      from date: Date) -> [T] {
        let range = date.curRecentSevenDayRange
        return query(type: type, start: range.start, end: range.end)
    }
    
    /// 查询本周
    public static func queryWeek<T: Storable>(type: T.Type,
                                              from date: Date) -> [T] {
        let range = date.curWeekRange
        return query(type: type, start: range.start, end: range.end)
    }
    
    /// 查询当月数据
    public static func queryMonth<T: Storable>(type: T.Type,
                                               from date: Date) -> [T] {
        let range = date.curMonthRange
        return query(type: type, start: range.start, end: range.end)
    }
    
    /// 查询当年的数据
    public static func queryYear<T: Storable>(type: T.Type,
                                              from date: Date) -> [T] {
        let range = date.curYearRange
        return query(type: type, start: range.start, end: range.end)
    }
}

